Skip to content

extra/sysext: cut install tree - #2773

Merged
supakeen merged 1 commit into
osbuild:mainfrom
supakeen:sysext-goes-brrr
Oct 22, 2026
Merged

supakeen merged 1 commit into
osbuild:mainfrom
supakeen:sysext-goes-brrr

Conversation

@supakeen

Copy link
Copy Markdown
Member

The sysext extras by default already layered on top of the reference pipeline (usually the OS pipeline) for their RPM transaction. This means that the sysext installs all RPMs from the reference pipeline plus any additional ones. This was on purpose since it's easy to reason about and it shows that the naive implementation works.

When standalone is turned on we don't do that and instead resolve the RPM transaction for the sysext separately.

Change the default behavior for non-standalone sysexts to copy in the reference tree (so the RPM database and interpreters necessary for scriptlets are present) and then cut down the to-be-installed RPMs by taking the subset of those that weren't already installed in the reference pipeline.

This really speeds up builds and due to the transaction nature of the depsolver we can guarantee that we can build on top of the reference pipeline in this way.

Some numbers, for an image type that layers three sysexts (podman, weechat, and tmux):

  • Before: 7m08s total.
  • After: 4m13s total.

The latter is basically the same time as the build without any system extensions.

Comment thread pkg/manifest/sysext.go Outdated
Comment on lines +115 to +131
func (p *SysextTree) additionalRPMTransactions(installed rpmmd.PackageList) depsolvednf.TransactionList {
byNEVRA := make(map[string]rpmmd.Checksum, len(installed))
for _, pkg := range installed {
byNEVRA[pkg.FullNEVRA()] = pkg.Checksum
}

transactions := make(depsolvednf.TransactionList, len(p.depsolveResult.Transactions))
for i, transaction := range p.depsolveResult.Transactions {
for _, pkg := range transaction {
if checksum, ok := byNEVRA[pkg.FullNEVRA()]; ok && checksum == pkg.Checksum {
continue
}
transactions[i] = append(transactions[i], pkg)
}
}
return transactions
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This got me thinking that the sysext transaction could be a separate one to begin with, right? Like if we add the sysext packages to the end of the depsolve chain as the last transaction, then that becomes the package list for the sysext (installable on top of the other transactions, which create the OS pipeline). So all this package filtering goes away.

What am I missing? Is it a problem with multiple sysexts?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're not missing anything here except my oversight. I think I pigeonholed myself into the result of the (already flattened) getPackageSetChains and maybe and older mental model of the depsolver where we might have not gotten the depsolve results back per transaction?

I'll adjust it to do them in a separate extension transaction and keep (most of the rest the same) so we don't need the funky filtering at all 🙂

The sysext extras by default already layered on top of the reference
pipeline (usually the OS pipeline) for their RPM transaction. This means
that the sysext installs *all* RPMs from the reference pipeline plus any
additional ones. This was on purpose since it's easy to reason about and
it shows that the naive implementation works.

When `standalone` is turned on we don't do that and instead resolve the
RPM transaction for the sysext separately.

Change the default behavior for non-standalone sysexts to copy in the
reference tree (so the RPM database and interpreters necessary for
scriptlets are present) and then cut down the to-be-installed RPMs by
tacking on an additional transaction and only putting those RPMs in the
install.

This really speeds up builds and due to the transaction nature of the
depsolver we can guarantee that we can build on top of the reference
pipeline in this way.

Some numbers, for an image type that layers three sysexts (`podman`,
`weechat`, and `tmux`):

- Before: 7m08s total.
- After:  4m13s total.

The latter is basically the same time as the build without any system
extensions.

Signed-off-by: Simon de Vlieger <cmdr@supakeen.com>
@supakeen

Copy link
Copy Markdown
Member Author

Adjusted the PR to use a separate transaction. For some reason my brain thought we didn't get results for RPMs back per transaction ... even though I wrote code that iterated over the transactions 😬

@achilleas-k achilleas-k left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very neat

@achilleas-k
achilleas-k added this pull request to the merge queue Oct 22, 2026
@supakeen
supakeen removed this pull request from the merge queue due to a manual request Oct 22, 2026
@supakeen
supakeen added this pull request to the merge queue Oct 22, 2026
Merged via the queue into osbuild:main with commit 5b48b22 Oct 22, 2026
55 checks passed
@supakeen
supakeen deleted the sysext-goes-brrr branch October 22, 2026 16:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants